package com.tommy.jiami.view;

import android.content.*;
import android.graphics.*;
import android.view.*;
import com.tommy.jiami.R;
import java.util.*;
import android.util.*;
import android.graphics.drawable.*;
import android.content.res.*;

public class LockPatternView extends View
{
	private static final int POINT_SIZE=4;
	private Point[][] points=new Point[3][3];
	private boolean isInit,isSelect,isFinish,movingNoPoint;
	private int width,height,lineWidth=10,offsetX,offsetY,pointR;
	private float mouseX,mouseY;
	private Drawable pointNormal,pointPressed,pointError;
	private Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);
	private List<Point> pointlist=new ArrayList<Point>();
	private OnPatternChangeListener listener;
	
	public LockPatternView(Context context){
		super(context);
	}
	
	public LockPatternView(Context context,AttributeSet attrs){
		super(context,attrs);
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		if(!isInit)initPoints();
		if(pointlist.size()>0){
			Point a=pointlist.get(0);
			for(int i=1;i<pointlist.size();i++){
				Point b=pointlist.get(i);
				line2Canvas(canvas,a,b);
				a=b;
			}
			if(movingNoPoint){
				line2Canvas(canvas,a,new Point(mouseX,mouseY));
			}
		}
		points2Canvas(canvas);
		
	}
	
	private void initPoints(){
		width=getWidth();
		height=getHeight();
		
		if(width>height){
			offsetX=(width-height)/2;
			width=height;
		}
		else{
			offsetY=(height-width)/2;
			height=width;
		}
		Resources res=getResources();
		pointNormal=res.getDrawable(R.drawable.point_normal);
		pointPressed=res.getDrawable(R.drawable.point_pressed);
		pointError=res.getDrawable(R.drawable.point_error);
		
		points[0][0]=new Point(offsetX+width/4,offsetY+width/4);
		points[0][1]=new Point(offsetX+width/2,offsetY+width/4);
		points[0][2]=new Point(offsetX+width-width/4,offsetY+width/4);
		
		points[1][0]=new Point(offsetX+width/4,offsetY+width/2);
		points[1][1]=new Point(offsetX+width/2,offsetY+width/2);
		points[1][2]=new Point(offsetX+width-width/4,offsetY+width/2);
			
		points[2][0]=new Point(offsetX+width/4,offsetY+width-width/4);
		points[2][1]=new Point(offsetX+width/2,offsetY+width-width/4);
		points[2][2]=new Point(offsetX+width-width/4,offsetY+width-width/4);
		pointR=width/14;
		
		int index=1;
		for(Point[] ps:points){
			for(Point point:ps){
				point.index=index;
				index++;
			}
		}
		
		isInit=true;
	}
	
	private void points2Canvas(Canvas canvas){
		for(Point[] ps:points){
			for(Point point:ps){
				switch (point.state){
					case Point.STATE_NORMAL:
						pointNormal.setBounds((int)point.x-pointR,(int)point.y-pointR,(int)point.x+pointR,(int)point.y+pointR);
						pointNormal.draw(canvas);
						break;
					case Point.STATE_PRESSED:
						pointPressed.setBounds((int)point.x-pointR,(int)point.y-pointR,(int)point.x+pointR,(int)point.y+pointR);
						pointPressed.draw(canvas);
						break;
					case Point.STATE_ERROR:
						pointError.setBounds((int)point.x-pointR,(int)point.y-pointR,(int)point.x+pointR,(int)point.y+pointR);
						pointError.draw(canvas);
						break;
				}
			}
		}
	}

	private void line2Canvas(Canvas canvas,Point a,Point b){
		paint.setStrokeWidth(lineWidth);
		if(a.state==Point.STATE_PRESSED){
			paint.setColor(0xff00ff00);
			canvas.drawLine(a.x,a.y,b.x,b.y,paint);
		}else{
			paint.setColor(0xffff0000);
			canvas.drawLine(a.x,a.y,b.x,b.y,paint);			
		}
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event){
		movingNoPoint=false;
		isFinish=false;
		mouseX=event.getX();
		mouseY=event.getY();
		Point point =null;
		switch (event.getAction()){
			case MotionEvent.ACTION_DOWN:
				resetPoint();
				point=checkSelectPoint();
				if(point!=null){
					isSelect=true;
				}
				break;
			case MotionEvent.ACTION_MOVE:
				if(isSelect){
					point=checkSelectPoint();
					if(point==null){
						movingNoPoint=true;
					}
				}
				break;
			case MotionEvent.ACTION_UP:
				isFinish=true;
				isSelect=false;
				break;
		}
		
		//选中重复检查
		if(!isFinish && isSelect && point!=null){
			if(crossPoint(point)){
				movingNoPoint=true;
			}else{
				point.state=Point.STATE_PRESSED;
				pointlist.add(point);
			}
		}
		
		//绘制结束
		if(isFinish&&pointlist.size()!=0){
			if(pointlist.size()==1){
				resetPoint();
			}else if(pointlist.size()<POINT_SIZE){
				errorPoint();
				if(listener!=null)listener.onPatternChange(null);
			}else{
				if(listener!=null){
					String password="";
					for(Point p:pointlist){
						password+=p.index;
					}
					listener.onPatternChange(password);
				}
			}
		}
		postInvalidate();
		return true;
	}
	
	private boolean crossPoint(Point point){
		if(pointlist.contains(point)){
			return true;
		}else{
			return false;
		}
	}
	
	private void resetPoint(){
		pointlist.clear();
		for(Point[] hpoint:points){
			for(Point point:hpoint){
				point.state=Point.STATE_NORMAL;
			}
		}
	}
	
	private void errorPoint(){
		for(Point point:pointlist){
			point.state=Point.STATE_ERROR;
		}
	}
	
	private Point checkSelectPoint(){
		for(Point[] ps:points){
			for(Point point:ps){
				if(Point.within(point.x,point.y,pointR,mouseX,mouseY)){
					return point;
				}
			}
		}
		return null;
	}
	
	public static class Point{
		public final static int STATE_NORMAL=0;
		public final static int STATE_PRESSED=1;
		public final static int STATE_ERROR=2;
		public float x,y;
		public int index=0,state=0;
		
		public Point(){
			
		}
		public Point(float x, float y)
		{
			this.x = x;
			this.y = y;
		}
		
		public static boolean within(float pointX,float pointY,float r,float mouseX,float mouseY){
			return Math.sqrt(Math.pow(pointX-mouseX,2)+Math.pow(pointY-mouseY,2))<r;
		}
		
	}
	
	public static interface OnPatternChangeListener{
		public void onPatternChange(String result);
	}
	
	public void setOnPatternChangeListener(OnPatternChangeListener l){
		listener=l;
	}
	
	public void reset(){
		resetPoint();
	}
	
	public void error(){
		errorPoint();
	}
}
